import time
import traceback
from threading import Thread
from rich.console import Console
from rich.live import Live
from rich.layout import Layout
from rich.panel import Panel
from rich.text import Text
from rich.table import Table
import configparser
import os,sys
import win32print

sys.path.append(os.path.dirname(os.path.abspath(__file__)))

from dataclasses import dataclass
@dataclass
class PrinterConfig:
    section: str
    IP: str
    name: str
    prn_files: list
    prn_files_count: list
    print_interval: int
    group_interval: int
    current_page: int
    target_page: int
    log_name: str
    receiver_email: str

# 打印状态标志
selected_printer: PrinterConfig = None
print_status = "暂停"  # 初始状态为"暂停"，["暂停","打印中","完成"]
Init_Description = "未启动本次打印，特别注意初始页数设置！"
print_status_description = Init_Description
monitor_status = "" # 记录监控的状态

# 创建控制台实例
console = Console()

def save_current_page_to_config():
    """保存当前打印页数到配置文件"""
    global selected_printer
    
    config = configparser.ConfigParser()
    config_file = '【双击修改】间歇打印配置.txt'
    
    # 读取配置文件
    config.read(config_file, encoding='utf-8')
    
    # 直接通过section名更新指定打印机的已打印页数
    if selected_printer.section in config:
        config[selected_printer.section]['已打印页数'] = str(selected_printer.current_page)
    
    # 保存更新后的配置（不保留注释）
    with open(config_file, 'w', encoding='utf-8') as configfile:
        config.write(configfile)
    
    logger.info(f"已保存当前打印页数 {selected_printer.current_page} 到配置文件")

def print_prn_file(prn_file,printer_name):
    global print_status_description
    computer_name = os.environ.get('COMPUTERNAME')
    if os.path.isfile(prn_file):
        print_status_description = "正常打印中，当前打印:"+prn_file
        try:
            hprinter = win32print.OpenPrinter(printer_name)
            jobs = win32print.EnumJobs(hprinter, 0, -1, 1)
            if len(jobs) > 0:
                print_status_description = "等待打印队列清空...(每2秒重新检查一次)"
                while len(jobs)>0:
                    jobs = win32print.EnumJobs(hprinter, 0, -1, 1)
                    time.sleep(2)
                print_status_description = "正常打印中，当前打印:"+prn_file
            
            # 发送数据
            import subprocess
            command = [
                "cmd", "/C",
                "copy", "/B",
                f'"{os.path.abspath(prn_file)}"',
                f'"\\\\{computer_name}\{printer_name}"'
            ]
            result = subprocess.run(
                " ".join(command),
                shell=True,
                check=True,
                capture_output=True,
                text=True
            )
                      
            # 检查输出（调试时使用）
            if result.returncode != 0:
                error_msg = f"打印失败: {result.stderr}"
                logger.error(error_msg)
                raise RuntimeError(error_msg)
        finally:
            win32print.ClosePrinter(hprinter)
    else:
        error_msg = f"错误：{prn_file}文件不存在！"
        logger.error(error_msg)
        raise RuntimeError(error_msg)

def printing():
    global selected_printer, print_status,print_status_description
    prns_len = len(selected_printer.prn_files)
    if prns_len==0:
        error_msg = "错误：文件列表为空！"
        logger.error(error_msg)
        raise RuntimeError(error_msg)
    
    # 记录打印任务开始
    logger.info("===== 开始打印任务 =====")
    logger.info(f"打印机序号: {selected_printer.section}")
    logger.info(f"打印机名称: {selected_printer.name}")
    logger.info(f"打印机IP: {selected_printer.IP}")
    logger.info(f"初始页数: {selected_printer.current_page}")
    logger.info(f"目标页数: {selected_printer.target_page}")
    logger.info(f"打印间隔: {selected_printer.print_interval}秒")
    logger.info(f"打印组间隔: {selected_printer.group_interval}秒")
    logger.info(f"PRN文件数量: {prns_len}")
    for i in range(0,len(selected_printer.prn_files)):
        logger.info(f"Prn文件名称{i+1}: {selected_printer.prn_files[i]}，其页数计数为：{selected_printer.prn_files_count[i]}")

    total_pages_count = 0
    index_select_count = [] # 若一个文件是3页，一个文件是2页，则[3,5]
    for c in selected_printer.prn_files_count:
        total_pages_count += c
        index_select_count.append(total_pages_count)
        
    
    while True:
        if print_status == "完成":
            break
        try:
            if print_status == "打印中":
                
                # 计算当前应该打印的文件索引（从0开始）
                ## 计算余数，当index_select_count=[3,5]时，余0则选file_index=0，余1~2时仍选file_index=0，余3~余4时选择file_index=1
                remainder = (selected_printer.current_page) % total_pages_count
                for i,count in enumerate(index_select_count):
                    if remainder < count :# 选择
                        file_index = i
                        break

                # 开始打印具体prn文件
                ## 标注描述
                print_status_description = "启动打印中"
                ## 获取打印文件名
                file_to_print = selected_printer.prn_files[file_index]
                ## 发送打印命令
                print_prn_file(file_to_print,selected_printer.name)
                ## 打印计数
                selected_printer.current_page += selected_printer.prn_files_count[file_index]
                ## 记录当前打印进度
                logger.info(f"当前打印进度: {selected_printer.current_page}/{selected_printer.target_page}页")
                
                ## 判断是否打印结束
                if selected_printer.current_page >= selected_printer.target_page:
                    selected_printer.current_page = selected_printer.target_page
                    print_status = "完成"
                    completion_msg = "已完成当前打印任务，现在可关闭本程序"
                    print_status_description = completion_msg
                    logger.info("===== 打印任务完成 =====")
                    logger.info(f"完成时间: {time.strftime('%Y-%m-%d %H:%M:%S')}")
                    logger.info(f"总打印页数: {selected_printer.current_page}页")
                    # 保存最终打印页数
                    save_current_page_to_config()

                # 等待间歇时间
                if file_index == 0:
                    # 打印首页，且非首次打印，等待打印组间隔
                    time.sleep(selected_printer.group_interval)
                elif file_index != 0:
                    time.sleep(selected_printer.print_interval)

        except KeyboardInterrupt as e:
            logger.warning("用户主动退出打印任务")
            print("用户主动退出")
        except Exception as e:
            # 捕获异常并显示,然后暂停
            if print_status != "完成":
                print_status = "暂停"
            pause_msg = "异常暂停，详情见下方异常信息"
            print_status_description = pause_msg
            logger.error(f"打印过程中发生异常: {str(e)}")
            logger.error(traceback.format_exc())
            show_exception(e)


def read_printer_config():
    """
    读取间歇打印配置文件，返回打印机列表
    
    返回:
        list: 包含所有打印机配置的列表，每个打印机是一个命名元组对象
              可以通过 printer[0].IP 等方式访问配置项
    """
    

    config = configparser.ConfigParser()
    config_file = '【双击修改】间歇打印配置.txt'
    
    # 读取配置文件
    config.read(config_file, encoding='utf-8')
    
    printers = []
    
    # 遍历所有打印机配置节
    global PrinterConfig
    for section in config.sections():
        if section.startswith('打印机'):
            # 获取所有Prn文件名称配置项
            prn_files = []
            prn_files_count = []
            i = 1
            while True:
                key = f'Prn文件名称{i}'
                if key in config[section]:
                    prn_files.append('prn文件存放/'+config[section][key])
                    if f'Prn文件{i}页数' in config[section]:
                        # 用于打印计数
                        prn_files_count.append(int(config[section][f'Prn文件{i}页数']))
                    else: # 默认计数为1
                        prn_files_count.append(1)
                    i += 1
                else:
                    # 若无则终止
                    break
            
            # 创建打印机配置对象
            printer = PrinterConfig(
                section=section,
                IP=config[section]['打印机IP地址'],
                name=config[section]['打印机名称'],
                prn_files=prn_files,
                prn_files_count=prn_files_count,
                print_interval=int(config[section]['打印间隔时间_秒']),
                group_interval=int(config[section]['打印组间隔时间_秒']),
                current_page=int(config[section]['已打印页数']),
                target_page=int(config[section]['打印总页数']),
                log_name=config[section]['打印日志名称'],
                receiver_email = config[section]['收信息邮箱']
            )
            
            printers.append(printer)

    return printers

def select_printer(printers):
    """让用户选择打印机"""
    global console
    console.print("[bold]可用的打印机列表:[/bold]", style="blue")
    for i, printer in enumerate(printers):
        console.print(f"[green]{i+1}.[/green] {printer.name} ({printer.log_name[:-4]})-已打印{printer.current_page}页/{printer.target_page}页")
    
    while True:
        try:
            choice = console.input("请选择打印机(输入编号): ")
            choice = int(choice) - 1
            if 0 <= choice < len(printers):
                selected_printer = printers[choice]
                return selected_printer
            console.print("[red]错误: 请输入有效的打印机编号[/red]")
        except ValueError:
            console.print("[red]错误: 请输入数字[/red]")
        except KeyboardInterrupt:
            logger.warning("用户主动退出程序")
            print("用户主动退出")
            exit()

def update_header(printer):
    """更新顶部打印机配置信息"""
    config_table = Table.grid(padding=(0, 2))
    config_table.add_column(style="bold cyan")
    config_table.add_column(style="bold green")
    
    config_data = {
        "共享名": printer.name,
        "IP地址": printer.IP,
        "打印间隔时间": f"{printer.print_interval}s",
        "打印组间隔时间": f"{printer.group_interval}s",
        "当前日志文件": f"{printer.log_name}s"
    }
    
    # 添加打印机基本信息
    for key, value in config_data.items():
        config_table.add_row(f"{key}:", value)
    
    config_table.add_row(f"打印文件列表（共{len(printer.prn_files)}份）:")

    # 显示所有prn文件
    for i in range(0,len(printer.prn_files)):
        config_table.add_row(f"Prn文件名称{i+1}: {selected_printer.prn_files[i]}，其页数计数为：{selected_printer.prn_files_count[i]}")

    
    header_panel = Panel(config_table, title="打印机当前配置", border_style="blue")
    global layout
    layout["header"].update(header_panel)

def update_body():
    """更新中间打印信息区域"""
    global print_status,monitor_status
    
    # 创建打印信息表格
    info_table = Table.grid(padding=(0, 2))
    info_table.add_column(style="bold yellow")
    info_table.add_column(style="bold white")
    
    info_table.add_row("当前打印页数:", f"{selected_printer.current_page}页")
    info_table.add_row("目标打印页数:", f"{selected_printer.target_page}页")
    info_table.add_row("当前打印状态:", f"[{'green' if print_status == '打印中' else 'red'}]{print_status}")
    info_table.add_row("具体状态描述:", f"[{'green' if print_status == '打印中' else 'red'}]{print_status_description}")
    info_table.add_row("后台监控状态:", f"{monitor_status}")
    
    # 计算进度百分比，限制在0-100之间
    progress = min(max(0, selected_printer.current_page / selected_printer.target_page * 100), 100) if selected_printer.target_page > 0 else 0
    
    # 计算进度条长度
    filled_length = min(20, max(0, int(round(progress / 5))))  # 四舍五入
    empty_length = 20 - filled_length
    
    # 构建进度条字符串
    progress_bar = (
        f"\[{'■' * filled_length}"
        f"{' ' * empty_length}] "
        f"{progress:.1f}%"
    )
    
    body_panel = Panel(
        info_table,
        title="打印任务信息",
        subtitle=progress_bar,
        border_style="green" if print_status == "打印中" else "red"
    )
    global layout
    layout["body"].update(body_panel)

def update_footer():
    """更新底部操作指引"""
    footer_text = Text()
    footer_text.append("用户操作指引:\n", style="bold")
    footer_text.append("按回车键: 暂停/继续打印，主动暂停时会自动保存当前已打印页数到配置txt\n", style="yellow")
    footer_text.append("按Ctrl+C: 退出程序\n", style="yellow")
    footer_text.append("修改配置请在“【双击修改】间歇打印配置.txt”文件中修改，并重启程序", style="yellow")
    
    footer_panel = Panel(footer_text, border_style="blue")
    global layout
    layout["footer"].update(footer_panel)

def show_exception(exception):
    """显示异常信息"""
    # 获取完整的异常堆栈信息
    exc_info = "".join(traceback.format_exception(type(exception), exception, exception.__traceback__))
    
    # 创建异常信息面板
    exc_panel = Panel(
        Text(exc_info, style="red"),
        title="[bold red]发生异常[/bold red]",
        border_style="red",
        subtitle="按任意键继续"
    )
    
    # 调整布局，显示异常区域
    global layout
    layout["header"].visible = False
    layout["footer"].visible = False
    layout["exception"].visible = True
    layout["exception"].update(exc_panel)


def user_input_handler():
    """处理用户输入的线程函数"""
    global print_status,layout,print_status_description,monitor_status
    
    while True:
        # 如果已经是完成状态，则不再监控
        if print_status == "完成":
            break
        try:
            input()  # 等待用户按回车
            # 如果正在显示异常，则隐藏异常区域
            if layout["exception"].visible:
                layout["exception"].visible = False
                layout["header"].visible = True
                layout["footer"].visible = True
                layout["exception"].size = 0
                
                continue
            
            # 切换打印状态
            if print_status == "打印中":
                print_status = "暂停"
                pause_msg = "用户主动暂停"
                print_status_description = pause_msg
                logger.info(pause_msg)
                # 保存当前打印页数
                save_current_page_to_config()
            elif print_status == "暂停":
                print_status = "打印中"
                resume_msg = "用户主动恢复打印"
                # monitor_status = None
                print_status_description = resume_msg
                logger.info(resume_msg)
        except KeyboardInterrupt as e:
            logger.warning("用户主动退出程序")
            print("用户主动退出")
        except Exception as e:
            # 捕获异常并显示,然后暂停
            show_exception(e)

# 解析打印机后台网站信息用
import requests,json,re
from urllib3 import disable_warnings
from urllib3.exceptions import InsecureRequestWarning
disable_warnings(InsecureRequestWarning) # 取消requests.get(verify=False)的warning SSL验证警告
from bs4 import BeautifulSoup
def get_DevStatus_HP_254():
    global selected_printer,monitor_status,print_status
    IP = selected_printer.IP
    url = f"http://{IP}/info_deviceStatus.html?tab=Home&menu=DevStatus"
    headers = {
        "Host": IP,
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
        "Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
        "Accept-Encoding": "gzip, deflate",
        "Connection": "keep-alive",
        "Referer": f"http://{IP}/info_suppliesStatus.html?tab=Home&menu=SupplyStatus",
        "Upgrade-Insecure-Requests": "1",
        "Priority": "u=0, i"
    }

    try:
        response = requests.get(url, headers=headers, verify=False, timeout=5)
    except requests.exceptions.Timeout:
        error_msg = "请求超时，请检查网络或重试"
        return True, error_msg
    html_text = response.text

    # 解析HTML
    soup = BeautifulSoup(html_text, 'html.parser')

    # 查找指定class和id的td标签
    target_td = soup.find('td', class_='itemLargeFont', id='deviceStatus_tableCell')

    if target_td:
        # 提取文本并处理&nbsp;（转换为空格）
        status_text = target_td.get_text(strip=True).replace('\xa0', ' ')
        # 去除所有空白字符（包括换行符、制表符等）并将多个连续空白字符替换为单个空格
        status_text = re.sub(r'\s+', '', status_text)
        ok_keywords = ["正在打印文档", "就绪","睡眠模式"]
        wait_keywords = ["正在初始化","正在清洁","正在散热","正在校准"]
        if any(keyword in status_text for keyword in ok_keywords):
            return True,"正常：" + status_text
        elif any(keyword in status_text for keyword in wait_keywords):
            return True,"等待："+status_text
        else:
            return False, "异常："+status_text
    else:
        error_msg = "失败：获取打印机状态失败"
        return False, error_msg

def get_DevStatus_HP_553():
    global selected_printer, monitor_status, print_status
    IP = selected_printer.IP
    url = f"http://{IP}/"
    headers = {
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
        "Accept-Encoding": "gzip, deflate, br, zstd",
        "Accept-Language": "zh-CN,zh;q=0.9",
        "Cache-Control": "max-age=0",
        "Connection": "keep-alive",
        "Cookie": "sessionId=0e95756ab6284df1901b2f7f521b8e5d",
        "Host": IP,
        "Sec-Fetch-Dest": "document",
        "Sec-Fetch-Mode": "navigate",
        "Sec-Fetch-Site": "none",
        "Sec-Fetch-User": "?1",
        "Upgrade-Insecure-Requests": "1",
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36",
        "sec-ch-ua": '"Google Chrome";v="135", "Not-A.Brand";v="8", "Chromium";v="135"',
        "sec-ch-ua-mobile": "?0",
        "sec-ch-ua-platform": '"Windows"'
    }

    try:
        response = requests.get(url, headers=headers, verify=False, timeout=5)
    except requests.exceptions.Timeout:
        error_msg = "请求超时，请检查网络或重试"
        return True, error_msg
    html_text = response.text

    # 解析HTML
    soup = BeautifulSoup(html_text, 'html.parser')

    # 查找指定id的span标签
    target_span = soup.find('span', id='MachineStatus')

    if target_span:
        # 提取文本并处理&nbsp;（转换为空格）
        status_text = target_span.get_text(strip=True).replace('\xa0', ' ')
        # 去除所有空白字符（包括换行符、制表符等）并将多个连续空白字符替换为单个空格
        status_text = re.sub(r'\s+', '', status_text)
        ok_keywords = ["正在打印", "就绪", "睡眠模式","耗材严重不足"]
        wait_keywords = ["正在初始化", "正在清洁", "正在散热", "正在校准","正在检查"]
        if any(keyword in status_text for keyword in ok_keywords):
            return True, "正常：" + status_text
        elif any(keyword in status_text for keyword in wait_keywords):
            return True, "等待：" + status_text
        else:
            return False, "异常：" + status_text
    else:
        error_msg = "失败：获取打印机状态失败"
        return False, error_msg

def get_DevStatus_Sharp_MX60():
    global selected_printer, monitor_status, print_status
    IP = selected_printer.IP
    url = f"http://{IP}/main.html"
    headers = {
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
        "Accept-Encoding": "gzip, deflate",
        "Accept-Language": "zh-CN,zh;q=0.9",
        "Cache-Control": "max-age=0",
        "Connection": "keep-alive",
        "Cookie": "sideBarflag=1; MFPSESSIONID=1500B2BD773D7BCEBE490807A1FAFE38B024B27EE9E6A4CD641320250619075418617200A8",
        "Host": IP,
        "Upgrade-Insecure-Requests": "1",
        "User-Agent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Mobile Safari/537.36"
    }

    try:
        response = requests.get(url, headers=headers, verify=False, timeout=5)
    except requests.exceptions.Timeout:
        error_msg = "请求超时，请检查网络或重试"
        return True, error_msg
    
    html_text = response.text

    # 解析HTML
    soup = BeautifulSoup(html_text, 'html.parser')

    # 直接通过class查找状态元素
    status_td = soup.find('td', class_='noserch')
    
    if status_td:
        # 获取状态文本
        status_text = status_td.get_text(strip=True)
        # 处理特殊字符和空白
        status_text = status_text.replace('\xa0', ' ')
        status_text = re.sub(r'\s+', '', status_text)
        
        # 使用原函数的状态判断逻辑
        ok_keywords = ["墨粉较少","打印机警告","更换墨粉回收容器","在线","忙碌","超过维护期"]
        wait_keywords = ["指定纸盒已被打开","盖板打开"]
        # 应报错信息“指定纸盒纸张用尽”
        
        if any(keyword in status_text for keyword in ok_keywords):
            return True, "正常：" + status_text
        elif any(keyword in status_text for keyword in wait_keywords):
            return True, "等待：" + status_text
        else:
            return False, "异常：" + status_text
    else:
        # 备用方法：尝试通过查找"当前状态"标签定位
        status_label = soup.find('td', string=lambda text: text and "当前状态" in text)
        if status_label and status_label.find_next_sibling('td'):
            status_text = status_label.find_next_sibling('td').get_text(strip=True)
            status_text = status_text.replace('\xa0', ' ')
            status_text = re.sub(r'\s+', ' ', status_text)
            return True, "正常：" + status_text
        
        error_msg = "失败：未找到状态信息"
        return False, error_msg

def monitor_printer_status():
    global selected_printer,monitor_status,print_status,print_status_description,Init_Description
    logger.info("已启动打印状态监控")
    series_of_254 = ["254","252","452"]
    series_of_553 = ["553","554"]
    series_of_MX60 = ["271","3081","3071"]
    if any(series in selected_printer.name for series in series_of_254):
        logger.info("【打印监控】确认为254系列打印机")
        get_DevStatus = get_DevStatus_HP_254
    elif any(series in selected_printer.name for series in series_of_553):
        logger.info("【打印监控】确认为553系列打印机")
        get_DevStatus = get_DevStatus_HP_553
    elif any(series in selected_printer.name for series in series_of_MX60):
        logger.info("【打印监控】确认为MX60系列打印机")
        get_DevStatus = get_DevStatus_Sharp_MX60
    else:
        logger.info("【打印监控】不能确认打印机系列，无法开启监控。")
        monitor_status = "不能确认打印机系列，无法开启监控。当前可以打印机系列:254,553,mx60."
        get_DevStatus = None
    while get_DevStatus:
        # 每1秒监控刷新一次
        time.sleep(1)
        # 如果已经是完成状态，则不再监控
        if print_status == "完成":
            break
        # 获取打印状态，若有异常则在直接在函数内将打印状态设为暂停
        ok, status= get_DevStatus()
        #监控主动处理打印状态，只有非用户主动暂停才操作，需特别注意monitor_status = status的时机
        if print_status_description != Init_Description and print_status_description != "用户主动暂停" and print_status!="完成":
            if ok:
                # 若打印正常,但标识为等待，则不发邮件，只等待。
                if status.startswith("等待"): 
                    print_status = "暂停"
                # 若打印正常,且标识不为等待
                else: 
                    print_status = "打印中"
                if status!=monitor_status:# 状态改变了，记录日志
                    monitor_status = status
                    logger.info(f"监控打印状态：{str(ok)}，描述：{status}")
            elif not ok:
                # 若监控到打印异常
                print_status = "暂停"
                print_status_description = status
                if status!=monitor_status:# 状态改变了，发邮件
                    try:
                        logger.warning(f"检测到打印机异常状态，发送邮件通知: {status}")
                        send_mail(status,selected_printer.receiver_email)
                    except Exception as e:
                        logger.error(f"发送邮件失败: {str(e)}")
                    # 判断往状态是否改变后再更新
                    monitor_status = status


# 用于邮件通知
import smtplib
from email.mime.text import MIMEText
from email.utils import formataddr

# 配置参数
smtp_server = "smtp.qq.com"  # SMTP服务器
port = 465
sender_email = "3568605467@qq.com"  # 发件邮箱
password = "zjkhvpkahiwrcjei"  # 邮箱密码/授权码

def send_mail(text,receiver_email):
    if not receiver_email:
        return
    # 创建邮件
    msg = MIMEText(text)
    msg["Subject"] = "打印机异常"
    msg["From"] = formataddr(("打印机监控系统", sender_email)) 
    msg["To"] = receiver_email
    # 发送邮件
    with smtplib.SMTP_SSL(smtp_server, port) as server:
        server.login(sender_email, password)
        server.sendmail(sender_email, receiver_email, msg.as_string())
        server.quit() 

def main():
    global layout,console,selected_printer
    # 读取打印机配置
    printers = read_printer_config()
    if not printers:
        console.print("[red]错误: 没有找到任何打印机配置[/red]")
        return
    
    # 让用户选择打印机
    selected_printer = select_printer(printers)
    
    # 创建布局，分割为顶部、中间和底部
    layout = Layout()
    layout.split(
        Layout(name="header", size=2+6+len(selected_printer.prn_files)),      # 顶部显示打印机配置
        Layout(name="body", size=7),        # 中间显示打印信息
        Layout(name="footer", size=6),      # 底部显示操作指引
        Layout(name="exception", ratio=1, visible=False)  # 异常信息区域，初始不可见
    )

    # 初始化日志
    import logging
    global logger
    logger = logging.getLogger("PrinterSystem")
    logger.setLevel(logging.DEBUG)
    # 建立一个filehandler来把日志记录在文件里，级别为debug以上., mode='w'是每次重写
    fh = logging.FileHandler(selected_printer.log_name)#, mode='w'
    fh.setLevel(logging.DEBUG)
    # 设置日志格式
    formatter = logging.Formatter("%(asctime)s - %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
    fh.setFormatter(formatter)
    #将相应的handler添加在logger对象中
    logger.addHandler(fh)
    logger.debug("打印系统初始化")

    # 初始化各个区域
    update_header(selected_printer)
    update_body()
    update_footer()
    
    # 启动打印线程
    print_thread = Thread(target=printing, daemon=True)
    print_thread.start()

    # 启动用户输入处理线程
    input_thread = Thread(target=user_input_handler, daemon=True)
    input_thread.start()

    # 启动监控线程
    monitor_thread = Thread(target=monitor_printer_status, daemon=True)
    monitor_thread.start()
    
    console.show_cursor(False)
    # 使用Live显示布局
    
    with Live(layout, console=console, screen=True, refresh_per_second=4):
        while True:
            try:
                update_body()  # 更新打印信息
            except KeyboardInterrupt as e:
                logger.warning("用户主动退出程序")
                print("用户主动退出")
                exit()
            except Exception as e:
                # 捕获异常并显示,然后暂停
                logger.error(f"主循环发生异常: {str(e)}")
                show_exception(e)


if __name__ == "__main__":
    main()